package cn.airfei.aircore.core.utils;

import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.Map;

/**
 * @description:
 * @author: air
 * @create: 2020-11-14 10:25
 */
public class MongoDbUtil {
    // 链接名称(表名)
    private final String collectionName;

    private Query query;

    private final MongoTemplate mongoTemplate = (MongoTemplate) SpringContextUtil.getBean("mongoTemplate");

    public MongoDbUtil(String collectionName) {
        this.collectionName = collectionName;
        query = new Query();
    }

    /**
     * 清除查询参数等
     *
     * @return
     */
    public MongoDbUtil clear() {
        this.query = new Query();
        return this;
    }


    /**
     * 构造查询参数
     *
     * @param map
     * @return
     */
    public MongoDbUtil query(Map<String, String> map) {
        for (String key : map.keySet()) {
            query.addCriteria(Criteria.where(key).is(map.get(key)));
        }
        return this;
    }

    /**
     * 构造查询参数
     *
     * @param key
     * @param value
     * @return
     */
    public MongoDbUtil query(String key, String value) {
        query.addCriteria(Criteria.where(key).is(value));
        return this;
    }


    /**
     * (qp-参数支持的操作符号有: is(=),ne(!=),gt(>),lt(<),gte(>=),lte(<=),in,regex(正则表达式,模糊查询))
     *
     * @param map
     * @return
     */
    public MongoDbUtil queryMixture(Map<String, String> map) {
        for (String key : map.keySet()) {
            assembleQuery(key, map.get(key));
        }
        return this;
    }


    /**
     * in 查询
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public MongoDbUtil queryIn(String key, Object min, Object max) {
        query.addCriteria(Criteria.where(key).in(min, max));
        return this;
    }


    /**
     * 限制条数
     *
     * @param limit
     * @return
     */
    public MongoDbUtil limit(Integer limit) {
        query.limit(limit);
        return this;
    }


    /**
     * @param key    要排序的key
     * @param isDesc 是否逆序
     * @return
     */
    public MongoDbUtil sort(String key, boolean isDesc) {
        if (isDesc) {
            query.with(Sort.by(Sort.Order.desc(key)));
        } else {
            query.with(Sort.by(Sort.Order.asc(key)));
        }
        return this;
    }


    /**
     * 返回结果
     *
     * @return
     */
    public Object find() {
        return mongoTemplate.find(query, Map.class, collectionName);
    }

    /**
     * 返回一条结果
     *
     * @return
     */
    public Object findOne() {
        return mongoTemplate.findOne(query, Map.class, collectionName);
    }


    /**
     * 查询所有
     *
     * @return
     */
    public Object findAll() {
        return mongoTemplate.findAll(Map.class, collectionName);
    }

    /**
     * 插入数据
     *
     * @param obj
     * @return
     */
    public Object insert(Object obj) {
        return mongoTemplate.insert(obj, collectionName);
    }

    /**
     * 统计
     *
     * @return
     */
    public Long count() {
        return mongoTemplate.count(query, collectionName);
    }

    /**
     * 根据traceId 查询
     *
     * @param traceId
     * @return
     */
    public Object selectByTraceId(String traceId) {
        Query query = new Query(Criteria.where("traceId").is(traceId)).with(Sort.by(Sort.Order.desc("createTime")));
        return mongoTemplate.find(query, Map.class, collectionName);
    }


    /**
     * (qp-参数支持的操作符号有: is(=),ne(!=),gt(>),lt(<),gte(>=),lte(<=),in,regex(正则表达式,模糊查询))
     *
     * @param key
     * @param value
     */
    private void assembleQuery(String key, String value) {
        String[] stringArr = key.split("-");
        if (stringArr[0].equals("qp") && stringArr.length == 3) {
            switch (stringArr[2]) {
                case "is":
                    query.addCriteria(Criteria.where(stringArr[1]).is(value));
                    break;
                case "ne":
                    query.addCriteria(Criteria.where(stringArr[1]).ne(value));
                    break;
                case "gt":
                    query.addCriteria(Criteria.where(stringArr[1]).gt(value));
                    break;
                case "lt":
                    query.addCriteria(Criteria.where(stringArr[1]).lt(value));
                    break;
                case "gte":
                    query.addCriteria(Criteria.where(stringArr[1]).gte(value));
                    break;
                case "in":
                    query.addCriteria(Criteria.where(stringArr[1]).in(value));
                    break;
                case "regex":
                    query.addCriteria(Criteria.where(stringArr[1]).regex(value));
                    break;
            }
        }
    }
}
